#ifndef PROCESS_HPP_
# define PROCESS_HPP_

# include <unistd.h>
# include <list>
# include "Utils/macros.hpp"

namespace wrappers {
namespace unix_utils {

/*!\class Process
 * \brief Wrapper for UNIX named pipe
 *
 * This class provide an object-oriented wrapper for UNIX Process utilities
 * Copies of this class cannot be made.
 * This class may be created only once per process. Use the method GetInstance()
 * to create and / or get the class instance.
 */
class Process {
public:
  /*! The type of the function executed by the forks when they are created */
  typedef void (ChildFunction)();

  /*! Destructor */
  virtual ~Process();

  /*! Create and / or get the class instance */
  static Process &GetInstance();

  /*! Equality operator overload
   * \param compareWith : The Process object to test equality with
   * \return true if `compareWith' and `this' are the same process
   */
  bool operator==(const Process &compareWith) const;
  /*! Inequality operator overload
   * \param compareWith : The Process object to test inequality with
   * \return true if `compareWith' and `this' are \b not the same process
   */
  bool operator!=(const Process &compareWith) const;

  /*! Fork the current process.
   * The child will execute the function specified with SetChildFunction
   * \return true if the process has successfully been forked
   */
  void Fork();

  /*! Kill all the children of the current process */
  void KillChildren();

  /*! Set the function that will be executed by the children
   * when they are created
   * \param function : the function executed by the children
   * \return a reference on this object
   */
  Process &SetChildFunction(const ChildFunction &function);
  /*! Remove the function that will be executed by the children
   * \return a reference on this object
   */
  Process &RemoveChildFunction();
  /*! Check if the process is a fork
   * \return true if the process is a fork, otherwise return else
   */
  bool IsAFork() const;
  /*! Get the PID of the process
   * \return The PID of the process
   */
  pid_t GetPid() const;

  /*! Get the process's arguments count
   * \return The process arguments count
   */
  int GetArgc() const;
  /*! Get the process's arguments values
   * \return The process arguments values
   */
  char** GetArgv() const;
  /*! Get the process's environment variables
   * \return The process environment variables
   */
  char** GetEnvp() const;

protected:
  Process(); /*!< Private default constructor (see GetInstance()) */
  /*! Disallow copy constructor and assignment operator */
  DISALLOW_COPY_AND_ASSIGN(Process);

  pid_t mPID; /*!< process pid */
  bool mIsAFork; /*!< Is this process a fork? */
  int mArgc; /*!< Arguments count */
  char **mArgv; /*!< Arguments values */
  char **mEnvp; /*!< Environment variables */
  std::list<pid_t> mForksList; /*!< List of the childs of the process */

  /*! The function to be executed by the child when it's created */
  ChildFunction *mChildFunction;
};

} /* !namespace unix_utils */
} /* !namespace wrappers */
#endif /* !PROCESS_HPP_ */
